package it.wzm.lightweightlog;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.Properties;



final class QueueDumper implements Runnable, Constant {

    private long dumpInterval;
    private Queue<? extends Entry> q;
    private Register<? extends Dumper> r;
    private boolean switcher;
    
    
    /**
     * Build a Queue Dumper 
     * @param p Custom set of property
     */
    QueueDumper(Properties p) {
        assert (p != null) : "Property null";
        this.init(p);
    }

    /**
     * Initialize our Queue dumper.
     */
    private void init(Properties p) {

        // looking for dump interval
        if (p.containsKey("dumpinterval")) {
            this.dumpInterval = (Long) p.get("dumpinterval");
        } else {
            this.dumpInterval = DEFAULT_DUMP_INTERVAL;

        // however by default we cannot dump less then 1 second
        }
        if (this.dumpInterval < 1000) {
            this.dumpInterval = DEFAULT_DUMP_INTERVAL;

        // these are needed by our QueueDumper
        }
        q = ObjectFactory.getQueue();
        r = ObjectFactory.getRegister();
                
        
        this.switcher=true;
    }
    
    void setSwitcher(boolean switcher) {
    	this.switcher=switcher;
    }
    
    /**
     * Implementing the run() method 
     */
    public void run() {

		// we cannot start a QueueDumper when register does not contain Dumper
        // or the Queue is not cumulable
        if (!q.isCumulable() || r.size() < 1) {
            return;
        }
        try { 	
            // just an infinite loop
            dumper:
            while (switcher) {
            	// we need to know if Log is still running...
            	// we first set switcher to false
            	setSwitcher(false);
            	// then we are going to retrieve all the active thread
            	// in our group. If you remember during Log instance 
            	// we gave the name of "Log" so we will look for a ThreadNamed
            	// log in our group...
            	ThreadGroup g = Thread.currentThread().getThreadGroup();            	
            	Thread[] T = new Thread[g.activeCount()];
            	g.enumerate(T, false);          	

            	logfinder:
            	for (Thread x: Arrays.asList(T)) {
            		// if it's found...we break the loop
            		// before we set switcher to true
            		// so that we can continue...
            		if (x.getName().equals("Log")) {  
            			setSwitcher(true);
            			break logfinder;
            		}
            	}
            	
                // get queue and a list of Entry	
            	LinkedList<? extends Entry> l;
            	synchronized(this) { 
            		l = q.retainAll();
            	};
            	
                // basic check if our queue
                // does contain any Entry...
                if (!l.isEmpty()) {
                    r.dispatchToDumper(l);
                    // clear entry from the list...
                    l.clear();
                    l=null;
                }
                // just pausing a while...
                Thread.sleep(dumpInterval);
            }

        } catch (InterruptedException e) {        	
            Log.serviceLog(e.getMessage());
        } finally {
        	// now it's time to free all resources
        	// just ask to ObjectFactory...
        	ObjectFactory.shutdown();
        }
    }    
}	
	
	

